package org.yzhzc.common.security.interceptor;

import cn.hutool.core.util.StrUtil;
import org.yzhzc.common.core.constants.Constants;
import org.yzhzc.common.core.constants.HttpConstants;
import org.yzhzc.common.core.utils.ThreadLocalUtil;
import org.yzhzc.common.security.service.TokenService;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * Token 拦截器，用于在请求处理前验证和解析 JWT Token，并将用户信息存储到 ThreadLocal 中。
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private TokenService tokenService;

    @Value("${jwt.secret}")
    private String secret; // 从配置文件中读取 JWT 的签名密钥

    /**
     * 在请求处理前执行，用于验证和解析 Token，并将用户信息存储到 ThreadLocal 中。
     *
     * @param request  HttpServletRequest 对象
     * @param response HttpServletResponse 对象
     * @param handler  当前请求的处理器
     * @return true 表示允许请求继续处理，false 表示拒绝请求
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 从请求头中获取 Token
        String token = this.getToken(request);

        // 如果 Token 为空，直接放行（可能是无需认证的接口）
        if (StrUtil.isEmpty(token)) {
            return true;
        }

        // 根据 Token 和密钥解析出 Claims（包含用户信息）
        Claims claims = tokenService.getClaims(token, secret);

        // 从 Claims 中提取用户 ID 和用户 Key
        Long userId = tokenService.getUserId(claims);
        String userKey = tokenService.getUserKey(claims);

        // 使用 ThreadLocal 存储用户信息，便于后续业务逻辑中使用
        ThreadLocalUtil.set(Constants.USER_ID, userId);
        ThreadLocalUtil.set(Constants.USER_KEY, userKey);

        // 扩展 Token 的有效期（例如，更新 Token 的过期时间）
        tokenService.extendToken(claims);

        // 允许请求继续处理
        return true;
    }

    /**
     * 在请求完成后执行，用于清理 ThreadLocal 中的用户信息，防止内存泄漏。
     *
     * @param request  HttpServletRequest 对象
     * @param response HttpServletResponse 对象
     * @param handler  当前请求的处理器
     * @param ex       请求处理过程中抛出的异常（如果有）
     * @throws Exception 如果清理过程中发生异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler, Exception ex) throws Exception {
        // 清理 ThreadLocal 中的用户信息
        ThreadLocalUtil.remove();
    }

    /**
     * 从请求头中获取 Token，并去掉 "Bearer " 前缀。
     *
     * @param request HttpServletRequest 对象
     * @return 处理后的 Token（去掉前缀后的值）
     */
    private String getToken(HttpServletRequest request) {
        // 从请求头中获取 "Authorization" 字段的值
        String token = request.getHeader(HttpConstants.AUTHENTICATION);

        // 如果 Token 不为空且以 "Bearer " 开头，去掉 "Bearer " 前缀
        if (StrUtil.isNotEmpty(token) && token.startsWith(HttpConstants.PREFIX)) {
            token = token.replaceFirst(HttpConstants.PREFIX, ""); // 去掉前缀
        }

        // 返回处理后的 Token
        return token;
    }
}